package org.jeecg.modules.demo.temple.job;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.sftp.SftpFactory;
import org.jeecg.common.sftp.SftpHelper;
import org.jeecg.common.sftp.SftpPool;
import org.jeecg.common.sftp.SftpProperties;
import org.jeecg.common.util.CsvUtil;
import org.jeecg.common.util.ZipUtil;
import org.jeecg.modules.demo.temple.order.entity.TempleActivityOrder;
import org.jeecg.modules.demo.temple.order.entity.TempleDonationOrder;
import org.jeecg.modules.demo.temple.order.service.ITempleActivityOrderService;
import org.jeecg.modules.demo.temple.order.service.ITempleDonationOrderService;
import org.jeecg.modules.demo.temple.pay.entity.TempleDzJxyhDetail;
import org.jeecg.modules.demo.temple.pay.entity.TempleDzJxyhSummary;
import org.jeecg.modules.demo.temple.pay.entity.TempleMerchantInfo;
import org.jeecg.modules.demo.temple.pay.service.ITempleDzJxyhDetailService;
import org.jeecg.modules.demo.temple.pay.service.ITempleDzJxyhSummaryService;
import org.jeecg.modules.demo.temple.pay.service.impl.TempleMerchantInfoServiceImpl;
import org.jeecg.modules.demo.temple.sys.entity.SysDepart;
import org.jeecg.modules.demo.temple.sys.service.ISysDepart;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Slf4j
public class JxyhReconciliationJob implements Job {

    private String parameter;

    public void setParameter(String parameter) {
        this.parameter = parameter;
    }

    @Autowired
    private TempleMerchantInfoServiceImpl templeMerchantInfoService;

    @Autowired
    private ITempleDzJxyhSummaryService templeDzJxyhSummaryService;

    @Autowired
    private ITempleDzJxyhDetailService templeDzJxyhDetailService;

    @Autowired
    private ITempleActivityOrderService templeActivityOrderService;

    @Autowired
    private ITempleDonationOrderService templeDonationOrderService;

    @Autowired
    private ISysDepart sysDepart;

    @Value("${sftp.jxyh.host}")
    private String host;

    @Value("${sftp.jxyh.port}")
    private int port;

    @Value("${sftp.jxyh.pool.max-idle}")
    private int maxIdle;

    @Value("${sftp.jxyh.pool.max-total}")
    private int maxTotal;

    @Value("${sftp.jxyh.pool.min-idle}")
    private int minIdle;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException{

            QueryWrapper<TempleMerchantInfo> queryWrapper = new QueryWrapper<TempleMerchantInfo>();
            queryWrapper.eq("pay_org","jxyh");

            List<TempleMerchantInfo> list = templeMerchantInfoService.list(queryWrapper);
            for (TempleMerchantInfo t : list) {
                String username = t.getUsername();
                String password = t.getPassword();
                String zipPassword = t.getZipPassword();
                String mechermantNo = t.getMerchantNo();
                String merchantId = t.getId();
                QueryWrapper<SysDepart> queryWrapper1 = new QueryWrapper();
                queryWrapper1.eq("org_code",t.getSysOrgCode());
                SysDepart depart = sysDepart.getOne(queryWrapper1);
                String departName = depart.getDepartName();
                String sysOrgCode = depart.getOrgCode();
                SimpleDateFormat aDate=new SimpleDateFormat("yyyyMMdd");
                Calendar cal=Calendar.getInstance();
                cal.add(Calendar.DATE,-1);
                Date yesterday=cal.getTime();
                if(!StringUtils.isEmpty(parameter)){
                    try {
                        yesterday = aDate.parse(parameter);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                SftpProperties sftpProperties = new SftpProperties();
                sftpProperties.setHost(host);
                sftpProperties.setPort(port);
                sftpProperties.setUsername(username);
                sftpProperties.setPassword(password);
                SftpProperties.Pool pool = new SftpProperties.Pool();
                pool.setMaxIdle(maxIdle);
                pool.setMaxTotal(maxTotal);
                pool.setMinIdle(minIdle);
                sftpProperties.setPool(pool);
                SftpFactory sftpFactory = new SftpFactory(sftpProperties);
                SftpPool sftpPool = new SftpPool(sftpFactory);
                SftpHelper sftpHelper = new SftpHelper(sftpPool);
                String dir = "/"+mechermantNo;
                String zipFileName = "DZ_"+ mechermantNo + "_" + aDate.format(yesterday) + ".csv.zip";//DZ_448435520000053_20220530.csv.zip
                String fileName = "DZ_"+ mechermantNo + "_" + aDate.format(yesterday) + ".csv";
                log.info("dir:"+dir);
                log.info("zipFileName:"+zipFileName);
                byte[] bytes = sftpHelper.download(dir, zipFileName);
                String path = "/usr/temple/dzfile/jxyh/"+mechermantNo+"/";
                //1.对账文件保存到本地
                try {
                    File file = new File(path);
                    if(!file.exists()){
                        file.mkdirs();
                    }
                    FileOutputStream fos = new FileOutputStream(path+zipFileName);
                    BufferedOutputStream bos = new BufferedOutputStream(fos);
                    bos.write(bytes);
                    bos.flush();
                    bos.close();
                }catch (IOException ex){
                    ex.printStackTrace();
                }
                //2.解压zip包
                try {
                    log.info("解压zip文件："+path+fileName);
                    log.info("解压目录："+path);
                    log.info("解压密码："+zipPassword);
                    ZipUtil.decompressZip(path + zipFileName, path, zipPassword);
                }catch (Exception e){
                    e.printStackTrace();
                }
                //3.读取对账文件写入数据库
                String recordNum;//总笔数
                String transactionAmountSum;//交易金额
                String liquidationAmountSum;//清算金额
                ArrayList<String[]> arrList =  CsvUtil.readCsvByCsvReader(path+fileName,"GBK");
                QueryWrapper<TempleDzJxyhSummary> rmSummaryWrapper = new QueryWrapper<TempleDzJxyhSummary>();
                rmSummaryWrapper.eq("tran_date",aDate.format(yesterday));
                rmSummaryWrapper.eq("merchant_no",mechermantNo);
                templeDzJxyhSummaryService.remove(rmSummaryWrapper);

                QueryWrapper<TempleDzJxyhDetail> rmDetailWrapper = new QueryWrapper<TempleDzJxyhDetail>();
                rmDetailWrapper.eq("tran_date",aDate.format(yesterday));
                rmDetailWrapper.eq("merchant_no",mechermantNo);
                templeDzJxyhDetailService.remove(rmDetailWrapper);
                for (int row = 0; row < arrList.size(); row++) {
                    if(row==0){
                        //3.1写入对账每日总表
                        recordNum = arrList.get(row)[0];
                        transactionAmountSum = arrList.get(row)[1];
                        liquidationAmountSum = arrList.get(row)[2];
                        TempleDzJxyhSummary templeDzJxyhSummary = new TempleDzJxyhSummary();
                        templeDzJxyhSummary.setMerchantId(merchantId);
                        templeDzJxyhSummary.setMerchantNo(mechermantNo);
                        templeDzJxyhSummary.setMerchantName(departName);
                        templeDzJxyhSummary.setLiqAmountSum(liquidationAmountSum);
                        templeDzJxyhSummary.setRecordNum(recordNum);
                        templeDzJxyhSummary.setTranAmountSum(transactionAmountSum);
                        templeDzJxyhSummary.setTranDate(aDate.format(yesterday));
                        templeDzJxyhSummaryService.save(templeDzJxyhSummary);
                    }else{
                        //3.2写入对账明细表
                        TempleDzJxyhDetail templeDzJxyhDetail = new TempleDzJxyhDetail();
                        templeDzJxyhDetail.setImpOrderNo(arrList.get(row)[0]);
                        templeDzJxyhDetail.setImpJnlNo(arrList.get(row)[1]);
                        templeDzJxyhDetail.setMechantOrerNo(arrList.get(row)[2]);
                        templeDzJxyhDetail.setTranTime(arrList.get(row)[3]);
                        templeDzJxyhDetail.setBizType(arrList.get(row)[4]);
                        templeDzJxyhDetail.setCustAcct(arrList.get(row)[5]);
                        templeDzJxyhDetail.setOrderAmount(arrList.get(row)[6]);
                        templeDzJxyhDetail.setRealAmount(arrList.get(row)[7]);
                        templeDzJxyhDetail.setBonusAmount(arrList.get(row)[8]);
                        templeDzJxyhDetail.setDiscountAmount(arrList.get(row)[9]);
                        templeDzJxyhDetail.setCouponsAmount(arrList.get(row)[10]);
                        templeDzJxyhDetail.setCardAmount(arrList.get(row)[11]);
                        templeDzJxyhDetail.setChannel(arrList.get(row)[12]);
                        templeDzJxyhDetail.setProfitAmount(arrList.get(row)[13]);
                        templeDzJxyhDetail.setOrderDesc(arrList.get(row)[14]);
                        templeDzJxyhDetail.setChannel(arrList.get(row)[15]);
                        templeDzJxyhDetail.setRefundOrderNo(arrList.get(row)[16]);
                        templeDzJxyhDetail.setMerchantId(merchantId);
                        templeDzJxyhDetail.setMerchantNo(mechermantNo);
                        templeDzJxyhDetail.setMerchantName(departName);
                        templeDzJxyhDetail.setTranDate(aDate.format(yesterday));
                        templeDzJxyhDetailService.save(templeDzJxyhDetail);
                        }


                }
                //4.自动对账，对比订单表和对账表

                //4.1对账表数据多于订单表，订单表需修改状态为Y
                QueryWrapper<TempleDzJxyhDetail> queryWrapper2 = new QueryWrapper<TempleDzJxyhDetail>();
                queryWrapper2.eq("merchant_no",mechermantNo);
                queryWrapper2.eq("tran_date",aDate.format(yesterday));
                List<TempleDzJxyhDetail> dzList = templeDzJxyhDetailService.list(queryWrapper2);

                List<String> donationList = new ArrayList<String>();
                List<String> activityList = new ArrayList<String>();
                for(TempleDzJxyhDetail detail : dzList){
                    String orderNo = detail.getMechantOrerNo();
                    if(orderNo.startsWith("D")){
                        donationList.add(orderNo.substring(orderNo.indexOf("D") + 1));
                    }else if(orderNo.startsWith("A")){
                        activityList.add(orderNo.substring(orderNo.indexOf("A") + 1));

                    }
                }

                String activityOrderCollectStr="";
                String donationOrderCollectStr="";
                for(String activityId:activityList){
                    activityOrderCollectStr = activityOrderCollectStr + "," + activityId;
                }
                for(String donationId:donationList){
                    donationOrderCollectStr = donationOrderCollectStr + "," + donationId;
                }
                log.info("activityOrderCollectStr:"+activityOrderCollectStr);
                log.info("donationOrderCollectStr:"+donationOrderCollectStr);
                //不为空才能执行，否则sql会少in的执行条件，导致全表修改。
                if(!CollectionUtils.isEmpty(activityList)) {
                    templeActivityOrderService.setIsPayState("Y", activityList);
                }
                if(!CollectionUtils.isEmpty(donationList)) {
                    templeDonationOrderService.setIsPayState("Y", donationList);
                }
                //4.2订单表数据多于对账表，订单表需修改状态为N
                SimpleDateFormat bDate=new SimpleDateFormat("yyyyMMddHHmmSS");
                try {
                    Date beginDate = bDate.parse(aDate.format(yesterday) + "000000");
                    Date endDate = bDate.parse(aDate.format(yesterday) + "235959");
                    QueryWrapper<TempleActivityOrder> queryWrapper3 = new QueryWrapper<TempleActivityOrder>();
                    queryWrapper3.eq("sys_org_code",sysOrgCode);
                    queryWrapper3.between("create_time",beginDate,endDate);
                    List<TempleActivityOrder> activityOrderList = templeActivityOrderService.list(queryWrapper3);


                    for(TempleActivityOrder activityOrder: activityOrderList){
                        String activityId = activityOrder.getId();
                        //活动订单id不在对账单里面

                        if(activityOrderCollectStr.indexOf(activityId) == -1){
                            if("Y".equals(activityOrder.getIsPay())) {
                                activityOrder.setIsPay("N");
                                templeActivityOrderService.updateById(activityOrder);
                                log.info("活动订单号：" + activityOrder.getId() + "重置支付状态为N");
                            }
                        }
                    }

                    QueryWrapper<TempleDonationOrder> queryWrapper4 = new QueryWrapper<TempleDonationOrder>();
                    queryWrapper4.eq("sys_org_code",sysOrgCode);
                    queryWrapper4.between("create_time",beginDate,endDate);
                    List<TempleDonationOrder> donationOrderList = templeDonationOrderService.list(queryWrapper4);
                    for(TempleDonationOrder donationOrder: donationOrderList){
                        String donationId = donationOrder.getId();
                        //捐赠订单id不在对账单里面
                        if(donationOrderCollectStr.indexOf(donationId) == -1){
                            if("Y".equals(donationOrder.getIsPay())) {
                                donationOrder.setIsPay("N");
                                templeDonationOrderService.updateById(donationOrder);
                                log.info("捐款订单号：" + donationOrder.getId() + "重置支付状态为N");
                            }

                        }
                    }


                }catch (ParseException e){
                    e.printStackTrace();
                }


            }


    }
}
